using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.PlayerLoop;

public class UIModule : SingletonBase<UIModule>
{
    // UI摄像机
    private Camera uiCamera;
    // UI根节点
    private Transform uiRoot;
    // UI字典，存储所有创建的UI
    private Dictionary<string, UIBase> uiDict = new Dictionary<string, UIBase>();
    // UI列表，存储所有创建的UI
    private List<UIBase> uiList = new List<UIBase>();
    // 可见UI列表，存储所有可见的UI
    private List<UIBase> uiVisibleList = new List<UIBase>();
    
    

    public void __init__()
    {
        uiCamera = GameObject.Find("UICamera").GetComponent<Camera>();
        uiRoot = GameObject.Find("UIRoot").transform;
    }

    #region 显示窗口

    // 显示窗口（外部调用）
    public T OpenWindow<T>() where T : UIBase, new()
    {
        System.Type type = typeof(T);
        string uiName = type.Name;
        UIBase uIBase = GetWindow(uiName);
        if (uIBase != null)
        {
            return OpenWindowInner(uiName) as T;
        }

        T t = new T();
        return InitializeWindow(t, uiName) as T;
    }
    
    // 显示窗口 （内部调用）
    private UIBase OpenWindowInner(string uiName)
    {
        UIBase uiBase = null;
        uiDict.TryGetValue(uiName, out uiBase);
        if (uiBase != null)
        {
            if (uiBase.gameObject != null && uiBase.Visible == false)
            {
                uiVisibleList.Add(uiBase);
                uiBase.transform.SetAsLastSibling();
                uiBase.SetVisible(true);
                uiBase.OnEnable();
                SetWindowMaskVisible();
            }
        }

        return uiBase;
    }    

    #endregion
    
    #region 隐藏窗口
    // 隐藏窗口 （外部接口）
    public void CloseWindow<T>(string uiName) where T : UIBase
    {
        CloseWindowInner(typeof(T).Name);
    }
    
    // 隐藏窗口 （内部调用）
    private void CloseWindowInner(string uiName)
    {
        UIBase uiBase = GetWindow(uiName);
        CloseWindowInner(uiBase);
    }

    // 隐藏窗口 （内部调用）
    private void CloseWindowInner(UIBase uiBase)
    {
        if (uiBase != null && uiBase.Visible)
        {
            uiVisibleList.Remove(uiBase);
            uiBase.SetVisible(false);
            uiBase.OnDisable();
            SetWindowMaskVisible();
        }
    }
    

    #endregion

    #region 销毁窗口

    // 销毁窗口 （外部调用）
    public void DestroyWindow<T>() where T : UIBase
    {
        DestroyWindowInner(typeof(T).Name);
    }
    
    // 销毁窗口 （内部调用）
    private void DestroyWindowInner(string uiName)
    {
        UIBase uiBase = GetWindow(uiName);
        DestroyWindowInner(uiBase);
    }
    
    // 销毁窗口 （内部调用）
    private void DestroyWindowInner(UIBase uiBase)
    {
        if (uiBase != null)
        {
            if (uiDict.ContainsKey(uiBase.Name))
            {
                uiDict.Remove(uiBase.Name);
                uiList.Remove(uiBase);
                uiVisibleList.Remove(uiBase);
            }
            uiBase.SetVisible(false);
            uiBase.OnDisable();
            uiBase.OnDestroy();
            SetWindowMaskVisible();
            GameObject.Destroy(uiBase.gameObject);
            Resources.UnloadUnusedAssets();
        }
    }

    /// <summary>
    /// 销毁所有窗口
    /// </summary>
    /// <param name="filterList">过滤列表</param>
    public void DestroyAllWindow(List<UIBase> filterList = null)
    {
        for (int i = uiList.Count - 1; i >= 0 ; i--)
        {
            UIBase uiBase = uiList[i];
            if (uiBase != null || (filterList != null && filterList.Contains(uiBase)))
            {
                continue;
            }
            DestroyWindowInner(uiBase.Name);
            Resources.UnloadUnusedAssets();
        }
    }
    #endregion

    
    // 初始化UI窗口
    public UIBase InitializeWindow(UIBase uiBase, string uiName)
    {
        // 1.生成对应UI的预制体
        GameObject go = TempLoadWindow(uiName);
        // 2.初始化
        if (go != null)
        {
            uiBase.gameObject = go;
            uiBase.transform = go.transform;
            uiBase.Canvas = go.GetComponent<Canvas>();
            uiBase.Canvas.worldCamera = uiCamera;
            uiBase.transform.SetAsLastSibling();
            uiBase.OnCreate();
            uiBase.SetVisible(true);
            uiBase.OnEnable();
            RectTransform rt = go.GetComponent<RectTransform>();
            rt.anchorMax = Vector2.one;
            rt.offsetMax = Vector2.zero;
            rt.offsetMin = Vector2.zero;
            uiDict.Add(uiName, uiBase);
            uiList.Add(uiBase);
            uiVisibleList.Add(uiBase);
            SetWindowMaskVisible();
            return uiBase;
        }
        Debug.LogError("没有加载到对应的窗口，窗口名字" + uiName);
        return null;
    }
    

    // 获取UI窗口
    public UIBase GetWindow(string uiName)
    {
        UIBase uiBase = null;
        uiDict.TryGetValue(uiName, out uiBase);
        return uiBase;
    }
    
    // 加载预制
    public GameObject TempLoadWindow(string uiName)
    {
        return GameObject.Instantiate<GameObject>(Resources.Load<GameObject>("UI/" + uiName));
    }
    
    // 设置遮罩 （单遮罩）
    private void SetWindowMaskVisible()
    {
        if (!UISetting.Instance.SINGMASK_SYSTEM)
        {
            return;
        }
        UIBase maxOrderWindowBase = null;//最大渲染层级的窗口
        int maxOrder = 0;//最大渲染层级
        int maxIndex = 0;//最大排序下标 在相同父节点下的位置下标
        //1.关闭所有窗口的Mask 设置为不可见
        //2.从所有可见窗口中找到一个层级最大的窗口，把Mask设置为可见
        for (int i = 0; i < uiVisibleList.Count; i++)
        {
            UIBase window = uiVisibleList[i];
            if (window != null && window.gameObject != null)
            {
                window.SetMaskVisible(false);
                // 初始化最大渲染层级窗口
                if (maxOrderWindowBase == null)
                {
                    maxOrderWindowBase = window;
                    maxOrder = window.Canvas.sortingOrder;
                    maxIndex = window.transform.GetSiblingIndex();
                }
                else
                {
                    //找到最大渲染层级的窗口，拿到它
                    if (maxOrder < window.Canvas.sortingOrder)
                    {
                        maxOrderWindowBase = window;
                        maxOrder = window.Canvas.sortingOrder;
                    }
                    //如果两个窗口的渲染层级相同，就找到同节点下最靠下一个物体，优先渲染Mask
                    else if (maxOrder == window.Canvas.sortingOrder && maxIndex < window.transform.GetSiblingIndex())
                    {
                        maxOrderWindowBase = window;
                        maxIndex = window.transform.GetSiblingIndex();
                    }
                }
            }
        }
        if (maxOrderWindowBase != null)
        {
            maxOrderWindowBase.SetMaskVisible(true);
        }
    }
    
}

